﻿using System;
using System.Configuration;
using System.IO;
using System.IO.Compression;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using OpenSSL.Properties;

namespace OpenSSL
{
    /// <summary>
    /// <para>修复 OpenSSL.dll 所需要的 运行环境.</para>
    /// <para>释放 OpenSSL.dll 需要的C++程序集 libeay32.dll ssleay32.dll 到系统的临时目录</para>
    /// </summary>
    internal static class __RecoverHelper
    {
        #region  尝试加载内嵌程序集

        internal static bool m_InitAssembly = false;


        [DllImport("kernel32.dll")]
        private static extern IntPtr LoadLibrary(string lpFileName); 






        internal static void InitResourceInteropAssembly()
        {
            if (m_InitAssembly) return;

            bool is64Proc = (IntPtr.Size == 8);
            var folder = (Path.GetTempPath() + "").TrimEnd('\\', '/') + string.Format(@"\OpenSSL.Net\{0}\", (is64Proc ? "x64" : "x86")); //系统临时目录
            var path1 = folder + "libeay32.dll";
            var path2 = folder + "ssleay32.dll";
            var bytes1 = is64Proc ? Resources.libeay32_x64_dll : Resources.libeay32_x86_dll;
            var bytes2 = is64Proc ? Resources.ssleay32_x64_dll : Resources.ssleay32_x86_dll;
            var bytes1Z = UnGZipBytes(bytes1);
            var bytes2Z = UnGZipBytes(bytes2);

            try { Directory.CreateDirectory(folder); } catch (ThreadAbortException) { throw; } catch (Exception) { }
            try { File.WriteAllBytes(path1, bytes1Z); } catch (ThreadAbortException) { throw; } catch (Exception) { }
            try { File.WriteAllBytes(path2, bytes2Z); } catch (ThreadAbortException) { throw; } catch (Exception) { }

            LoadLibrary(path1);
            LoadLibrary(path2);
            m_InitAssembly = true;
        }


        #region  压缩 和 解压缩 字节组

        /// <summary>
        /// 将一个 字节流 压缩成GZip字节流
        /// </summary>
        public static byte[] EnGZipBytes(byte[] sourceBytes)
        {
            if (sourceBytes == null) return null;
            if (sourceBytes.Length <= 0) return new byte[0];

            using (System.IO.MemoryStream memoryStream = new System.IO.MemoryStream())
            {
                using (GZipStream zipStream = new GZipStream(memoryStream, CompressionMode.Compress))
                {
                    zipStream.Write(sourceBytes, 0, sourceBytes.Length);
                    zipStream.Close();
                }

                return memoryStream.ToArray();
            }
        }
        /// <summary>
        /// 将一个 GZip字节流 解压成 原始字节流
        /// </summary>
        public static byte[] UnGZipBytes(byte[] zipBytes)
        {
            if (zipBytes == null) return null;
            if (zipBytes.Length <= 0) return new byte[0];

            byte[] sourceBytes = null;
            using (System.IO.MemoryStream memoryStream = new System.IO.MemoryStream(zipBytes))
            {
                using (GZipStream zipStream = new GZipStream(memoryStream, CompressionMode.Decompress))
                {
                    using (System.IO.MemoryStream sourceStream = new System.IO.MemoryStream())
                    {
                        do
                        {
                            byte[] buffer = new byte[1024];
                            int read = zipStream.Read(buffer, 0, buffer.Length);
                            if (read >= 1) sourceStream.Write(buffer, 0, read);

                            if (read <= 0) break;
                            if (read < buffer.Length) break;
                        } while (true);

                        zipStream.Close();
                        sourceBytes = sourceStream.ToArray();
                    }
                }
            }
            return sourceBytes;
        }

        #endregion


        #endregion

    }
}
